package com.devilvan.betrice.europeacademy.controller;

import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.fastjson.JSONObject;
import com.devilvan.betrice.common.BetriceResultCode;
import com.devilvan.betrice.common.BetriceResultVo;
import com.devilvan.betrice.europeacademy.constant.EuropeAcademyRedisConstant;
import com.devilvan.betrice.europeacademy.entity.EuropeAcademyExportEntity;
import com.devilvan.betrice.europeacademy.entity.FindAllAvatarEntity;
import com.devilvan.betrice.europeacademy.po.EuropeAcademyHeaderPo;
import com.devilvan.betrice.europeacademy.service.EuropeAcademyHeaderService;
import com.devilvan.betrice.europeacademy.vo.EuropeAcademyExcelVo;
import com.devilvan.betrice.export.pojo.EasyexcelWriteDto;
import com.devilvan.betrice.request.component.JsoupComponent;
import com.devilvan.betrice.util.UCopy;
import com.devilvan.betrice.util.UEmpty;
import com.xxl.job.core.handler.annotation.XxlJob;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutionException;

/**
 * @author Evad.Wu
 * @Description 欧洲学术 控制器
 * https://www.ae-info.org/ae/Acad_Main/List_of_Members/ListMembersBySection?type=listsection&pagenr=0
 * @date 2022-09-05
 */
@RestController
@RequestMapping(value = "europeAcademyController")
@Tag(name = "欧洲学术 控制器")
public class EuropeAcademyController {
    private static final String EUROPE_ACADEMY_URL = "https://www.ae-info.org/ae/Acad_Main/List_of_Members/ListMembersBySection?type=listsection&pagenr=-1";

    @Resource(name = "jsoupComponent")
    private JsoupComponent jsoupComponent;
    @Resource(name = "betriceRedisTemplate")
    private RedisTemplate<String, Object> redisTemplate;

    @Resource(name = "europeAcademyHeaderServiceImpl")
    private EuropeAcademyHeaderService europeAcademyHeaderService;

    /**
     * 注意：仅初次执行即可
     * 步骤一：采集欧洲学术各个成员的明细页面URL，保存到redis中
     *
     * @return 形式上返回
     */
    @Operation(summary = "注意：仅初次执行即可 步骤一：采集欧洲学术各个成员的明细页面URL，保存到redis中")
    @GetMapping(value = "doEuropeAcademyDetailUrl")
    public BetriceResultVo<Void> doEuropeAcademyDetailUrl() {
        BetriceResultVo<Void> betriceResultVo = new BetriceResultVo<>(false);
        List<String> detailUrlList = new ArrayList<>();
        Element body = jsoupComponent.getBody(EUROPE_ACADEMY_URL);
        Elements detailList = body.select("span[class='name'] b a");
        for (Element detail : detailList) {
            String href = detail.attr("href");
            detailUrlList.add(href);
        }
        try {
            redisTemplate.opsForList().rightPushAll(EuropeAcademyRedisConstant.KEY_EUROPE_ACADEMY_MEMBER_DETAIL, detailUrlList);
            betriceResultVo.result(BetriceResultCode.SUCCESS_200.getCode());
        } catch (Exception e) {
            e.printStackTrace();
            betriceResultVo.result(BetriceResultCode.FAILED_500.getCode());
        }
        return betriceResultVo;
    }

    /**
     * 步骤二：采集欧洲学术各个成员的明细页面
     *
     * @return 形式返回
     */
    @XxlJob(value = "doEuropeAcademy")
    @Operation(summary = "步骤二：采集欧洲学术各个成员的明细页面")
    @GetMapping(value = "doEuropeAcademy")
    public BetriceResultVo<EuropeAcademyHeaderPo> doEuropeAcademy() {
        String url = Objects.requireNonNull(redisTemplate.opsForList().leftPop(EuropeAcademyRedisConstant.KEY_EUROPE_ACADEMY_MEMBER_DETAIL)).toString();
        BetriceResultVo<EuropeAcademyHeaderPo> betriceResultVo = null;
        try {
            betriceResultVo = europeAcademyHeaderService.doEuropeAcademy(url).get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        return betriceResultVo;
    }

    /**
     * 步骤三：处理采集异常的URL，手工重试
     *
     * @return 形式返回
     */
    @Operation(summary = "步骤三：处理采集异常的URL，手工重试")
    @GetMapping(value = "doEuropeAcademyExceptionHandler")
    public BetriceResultVo<EuropeAcademyHeaderPo> doEuropeAcademyExceptionHandler() {
        String url = Objects.requireNonNull(redisTemplate.opsForList().leftPop(EuropeAcademyRedisConstant.KEY_EUROPE_ACADEMY_MEMBER_EXCEPTION)).toString();
        BetriceResultVo<EuropeAcademyHeaderPo> betriceResultVo = null;
        try {
            betriceResultVo = europeAcademyHeaderService.doEuropeAcademy(url).get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        return betriceResultVo;
    }

    /**
     * 单次执行：下载所有成员的头像图片
     *
     * @return 形式回调
     */
    @Operation(summary = "单次执行：下载所有成员的头像图片")
    @GetMapping(value = "doDownloadAllMembershipAvatar")
    public BetriceResultVo<Void> doDownloadAllMembershipAvatar() {
        BetriceResultVo<Void> betriceResultVo = new BetriceResultVo<>();
        int finish = 0;
        try {
            List<FindAllAvatarEntity> findAllAvatarEntityList = europeAcademyHeaderService.findAllMembershipAvatar();
            for (FindAllAvatarEntity entity : findAllAvatarEntityList) {
                Boolean downloadAvatarFlag = europeAcademyHeaderService.downloadAllMembershipAvatar(entity).get();
                if (downloadAvatarFlag) {
                    finish++;
                }
            }
            betriceResultVo.setSuccess(true);
            betriceResultVo.setHandleCount(finish);
            betriceResultVo.result(BetriceResultCode.SUCCESS_200.getCode(), "操作成功！");
        } catch (Exception e) {
            e.printStackTrace();
            betriceResultVo.result(BetriceResultCode.FAILED_500.getCode(), "操作失败：" + e);
        }
        return betriceResultVo;
    }

    /**
     * 可选：根据成员ID查询数据库，将结果集导出。注：membershipId为null时，导出全部
     *
     * @param request {@link com.devilvan.betrice.europeacademy.vo.EuropeAcademyExcelVo}
     * @return 形式回调
     */
    @Operation(summary = "可选：根据成员ID查询数据库，将结果集导出。注：membershipId为null时，导出全部")
    @GetMapping(value = "doExportExcel")
    public BetriceResultVo<Void> doExportExcel(@RequestBody String request) {
        BetriceResultVo<Void> betriceResultVo = new BetriceResultVo<>(false);
        EuropeAcademyExcelVo europeAcademyExcelVo = JSONObject.parseObject(request, EuropeAcademyExcelVo.class);
        String excelVoSuffix = europeAcademyExcelVo.getSuffix();
        ExcelTypeEnum validSuffix = matchConversion(excelVoSuffix);
        if (null == validSuffix) {
            betriceResultVo.setMsg("后缀类型错误，应为：XLS、XLSX、CSV之一");
            return betriceResultVo;
        }
        EasyexcelWriteDto easyexcelWriteDto = new EasyexcelWriteDto();
        UCopy.fullCopy(europeAcademyExcelVo, easyexcelWriteDto);
        easyexcelWriteDto.setSuffix(validSuffix);
        easyexcelWriteDto.setClassType(EuropeAcademyExportEntity.class);
        List<Long> membershipIdList = europeAcademyExcelVo.getMembershipIdList();
        betriceResultVo = UEmpty.isNotEmpty(membershipIdList) ?
                europeAcademyHeaderService.doExportExcelByMembershipIdList(easyexcelWriteDto, membershipIdList) :
                europeAcademyHeaderService.doExportExcelAll(easyexcelWriteDto);
        return betriceResultVo;
    }

    private ExcelTypeEnum matchConversion(String validSuffix) {
        ExcelTypeEnum[] excelTypeEnums = ExcelTypeEnum.values();
        for (ExcelTypeEnum excelTypeEnum : excelTypeEnums) {
            if (excelTypeEnum.name().equalsIgnoreCase(validSuffix)) {
                return excelTypeEnum;
            }
        }
        return null;
    }
}
